#include <iostream>
#include <immintrin.h>
#include <xmmintrin.h> //SSE
#include <emmintrin.h> //SSE2
#include <pmmintrin.h> //SSE3
#include <tmmintrin.h> //SSSE3
#include <smmintrin.h> //SSE4.1
#include <nmmintrin.h> //SSSE4.2
#include <immintrin.h> //AVX、AVX
#include<mpi.h>
#include<fstream>
#include<string>
#include<vector>
#include<sys/time.h>
#include<math.h>
#include<omp.h>
using namespace std;
int pThreadNum = 1;
bool* isNull;

string getbeiAddr(int which)
{
    switch (which) {
    case 1:
        return "/e/搞死小圆/Groebner/测试样例1 矩阵列数130，非零消元子22，被消元行8/被消元行.txt";
    case 2:
        return "/e/搞死小圆/Groebner/测试样例2 矩阵列数254，非零消元子106，被消元行53/被消元行.txt";
    case 3:
        return "/e/搞死小圆/Groebner/测试样例3 矩阵列数562，非零消元子170，被消元行53/被消元行.txt";
    case 4:
        return "/e/搞死小圆/Groebner/测试样例4 矩阵列数1011，非零消元子539，被消元行263/被消元行.txt";
    case 5:
        return "/e/搞死小圆/Groebner/测试样例5 矩阵列数2362，非零消元子1226，被消元行453/被消元行.txt";
    case 6:
        return "/e/搞死小圆/Groebner/测试样例6 矩阵列数3799，非零消元子2759，被消元行1953/被消元行.txt";
    case 7:
        return "/e/搞死小圆/Groebner/测试样例7 矩阵列数8399，非零消元子6375，被消元行4535/被消元行.txt";
    case 8:
        return "/e/搞死小圆/Groebner/测试样例8 矩阵列数23045，非零消元子18748，被消元行14325/被消元行.txt";
    case 9:
        return "/e/搞死小圆/Groebner/测试样例9 矩阵列数37960，非零消元子29304，被消元行14921/被消元行.txt";
    case 10:
        return "/e/搞死小圆/Groebner/测试样例10 矩阵列数43577，非零消元子39477，被消元行54274/被消元行.txt";
    case 11:
        return "/e/搞死小圆/Groebner/测试样例11 矩阵列数85401，非零消元子5724，被消元行756/被消元行.txt";
    }
}
string getziAddr(int which)
{
    switch (which) {
    case 1:
        return "/e/搞死小圆/Groebner/测试样例1 矩阵列数130，非零消元子22，被消元行8/消元子.txt";
    case 2:
        return "/e/搞死小圆/Groebner/测试样例2 矩阵列数254，非零消元子106，被消元行53/消元子.txt";
    case 3:
        return "/e/搞死小圆/Groebner/测试样例3 矩阵列数562，非零消元子170，被消元行53/消元子.txt";
    case 4:
        return "/e/搞死小圆/Groebner/测试样例4 矩阵列数1011，非零消元子539，被消元行263/消元子.txt";
    case 5:
        return "/e/搞死小圆/Groebner/测试样例5 矩阵列数2362，非零消元子1226，被消元行453/消元子.txt";
    case 6:
        return "/e/搞死小圆/Groebner/测试样例6 矩阵列数3799，非零消元子2759，被消元行1953/消元子.txt";
    case 7:
        return "/e/搞死小圆/Groebner/测试样例7 矩阵列数8399，非零消元子6375，被消元行4535/消元子.txt";
    case 8:
        return "/e/搞死小圆/Groebner/测试样例8 矩阵列数23045，非零消元子18748，被消元行14325/消元子.txt";
    case 9:
        return "/e/搞死小圆/Groebner/测试样例9 矩阵列数37960，非零消元子29304，被消元行14921/消元子.txt";
    case 10:
        return "/e/搞死小圆/Groebner/测试样例10 矩阵列数43577，非零消元子39477，被消元行54274/消元子.txt";
    case 11:
        return "/e/搞死小圆/Groebner/测试样例11 矩阵列数85401，非零消元子5724，被消元行756/消元子.txt";

    }
}
int getHang(int which)
{
    switch (which)
    {
    case 1:
        return 8;
    case 2:
        return 53;
    case 3:
        return 53;
    case 4:
        return 263;
    case 5:
        return 453;
    case 6:
        return 1953;
    case 7:
        return 4535;
    case 8:
        return 14325;
    case 9:
        return 14291;
    case 10:
        return 54274;
    case 11:
        return 756;
    }
}
int getLie(int which)
{
    switch (which)
    {
    case 1:
        return 130;
    case 2:
        return 254;
    case 3:
        return 562;
    case 4:
        return 1011;
    case 5:
        return 2362;
    case 6:
        return 3799;
    case 7:
        return 8399;
    case 8:
        return 23075;
    case 9:
        return 37960;
    case 10:
        return 43577;
    case 11:
        return 85401;
    }
}


void showLie(unsigned int* m, int lie)
{
    for (int i = 0; i < lie; i++)
    {
        cout << m[i] << " ";
    }
    cout << endl;
}
unsigned int** init(int hang, int lie)
{
    unsigned int** m = new unsigned int* [hang];
    for (int i = 0; i < hang; i++)
    {
        m[i] = new unsigned int[lie];
        for (int p = 0; p < lie; p++)
        {
            m[i][p] = 0;
        }
    }
    return m;
}
int qujian(int nowliePos, int lie)
{
    //97,65,33,1
    //假设不弄32了，分成每五个一组。那么125是和129一样都是第0组的.130 - 125 - 1 /5 = 0
    return (lie - nowliePos - 1) / 32;
}
int liePos(int nowliePos, int lie)
{
    //还是假设五个一组。120是第1组第4位，130 - (1*5 + 120) = 5
    return lie - (((lie - nowliePos - 1) / 32) * 32 + nowliePos) - 1;
}
unsigned int bit2int(int* m)//统一在左边的是高位
{
    unsigned int result = 0;
    for (int i = 0; i < 32; i++)
    {
        if (m[i])result += pow(2, 31 - i);
    }
    return result;
}
void showM(unsigned int** m, int hang, int lie)
{
    for (int i = 0; i < hang; i++)
    {
        showLie(m[i], lie);
        cout << endl;
    }
}
int* int2bit(unsigned int decimal_num)
{
    int* pos = new int[32];
    unsigned int mask = 1 << 31; // 定义掩码，初始值为1左移31位
    for (int i = 0; i < 32; i++) {
        // 判断当前位是0还是1，并输出
        if ((decimal_num & mask) == 0) {
            pos[i] = 0;
        }
        else {
            pos[i] = 1;
        }
        // 将掩码右移一位，判断下一位
        mask = mask >> 1;
    }
    return pos;
}
void testShow(unsigned int** m, int hang, int lie, int lieOf01)
{
    int* temp;
    for (int i = 0; i < hang; i++)
    {
        for (int p = 0; p < lie; p++)
        {
            temp = int2bit(m[i][p]);
            for (int q = 0; q < 32; q++)
            {
                if (temp[q])
                {
                    cout << lieOf01 - 32 * p - q - 1 << " ";
                }
            }
        }
        cout << endl;
    }
}

unsigned int** write(string beiAddr, int beihang, int beilie, int rank,int numProcesses)
{
    int lie = (beilie / 32 * 32 == beilie) ? beilie / 32 : beilie / 32 + 1;
    int yu = lie - beilie;
    unsigned int** m = new unsigned int* [beihang];
    for (int i = 0; i < beihang; i++)
    {
        m[i] = new unsigned int[lie];
        for (int p = 0; p < lie; p++)
            m[i][p] = 0;
    }
    ifstream fin;
    fin.open(beiAddr.c_str(), ios::in);
    int* pos = new int[32];
    for (int i = 0; i < 32; i++)
        pos[i] = 0;
    char ch;
    int temp = 0, nowPos = 0, bitclimiter = 0, whetherBegin = 1, nowQujian = 0, lastQujian = 0;
    //现在要看你是第几个rank了。分进程读取数据
 

    while (fin.get(ch))
    {
        if (ch >= '0' && ch <= '9')
        {
            temp *= 10;
            temp += ch - '0';
        }
        else if (ch == ' ')
        {
            if (whetherBegin)
            {
                lastQujian = qujian(temp, beilie); //注意这里穿的是int的列长度。
                bitclimiter = liePos(temp, beilie);//算出了temp所在的区间的位置。
                pos[bitclimiter] = 1;//该区间下对应位置记为1
                whetherBegin = 0;
            }
            else
            {
                nowQujian = qujian(temp, beilie);//算出了temp所在的区间
                if (nowQujian != lastQujian)
                {
                    m[nowPos][lastQujian] = bit2int(pos);
                    for (int i = 0; i < 32; i++)
                        pos[i] = 0;
                }
                bitclimiter = liePos(temp, beilie);//算出了temp所在的区间的位置。
                pos[bitclimiter] = 1;//该区间下对应位置记为1
                lastQujian = nowQujian;
            }
            temp = 0;
        }
        else if (ch == '\n')
        {
            m[nowPos][lastQujian] = bit2int(pos);
            for (int i = 0; i < 32; i++)
                pos[i] = 0;
            whetherBegin = 1;
            nowPos++;
            temp = 0;
            nowQujian = 0;
            lastQujian = 0;
        }
    }
    fin.close();


    return m;
}
unsigned int** MPIwrite(string beiAddr, int beihang, int beilie, int rank, int numProcesses)
{
    int lie = (beilie / 32 * 32 == beilie) ? beilie / 32 : beilie / 32 + 1;
    int yu = lie - beilie;
    unsigned int** m = new unsigned int* [beihang];
    for (int i = 0; i < beihang; i++)
    {
        m[i] = new unsigned int[lie];
        for (int p = 0; p < lie; p++)
            m[i][p] = 0;
    }
    ifstream fin;
    fin.open(beiAddr.c_str(), ios::in);
    int* pos = new int[32];
    for (int i = 0; i < 32; i++)
        pos[i] = 0;
    char ch;
    int temp = 0, nowPos = 0, bitclimiter = 0, whetherBegin = 1, nowQujian = 0, lastQujian = 0;
    //现在要看你是第几个rank了。分进程读取数据
    int howmany_hang_i_will_process = (beihang == (beihang / numProcesses) * numProcesses) ? beihang / numProcesses : beihang / numProcesses + 1;
    int startLine = howmany_hang_i_will_process * rank;



    for (int i = 0; i < startLine; i++)
    {
        fin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    }

    while (fin.get(ch) && nowPos < howmany_hang_i_will_process)
    {
        if (ch >= '0' && ch <= '9')
        {
            temp *= 10;
            temp += ch - '0';
        }
        else if (ch == ' ')
        {
            if (whetherBegin)
            {
                lastQujian = qujian(temp, beilie); //注意这里穿的是int的列长度。
                bitclimiter = liePos(temp, beilie);//算出了temp所在的区间的位置。
                pos[bitclimiter] = 1;//该区间下对应位置记为1
                whetherBegin = 0;
            }
            else
            {
                nowQujian = qujian(temp, beilie);//算出了temp所在的区间
                if (nowQujian != lastQujian)
                {
                    m[nowPos + startLine][lastQujian] = bit2int(pos);
                    for (int i = 0; i < 32; i++)
                        pos[i] = 0;
                }
                bitclimiter = liePos(temp, beilie);//算出了temp所在的区间的位置。
                pos[bitclimiter] = 1;//该区间下对应位置记为1
                lastQujian = nowQujian;
            }
            temp = 0;
        }
        else if (ch == '\n')
        {
            m[nowPos + startLine][lastQujian] = bit2int(pos);
            for (int i = 0; i < 32; i++)
                pos[i] = 0;
            whetherBegin = 1;
            nowPos++;
            temp = 0;
            nowQujian = 0;
            lastQujian = 0;
        }
    }
    fin.close();



    //然后通讯。
    for (int i = 0; i < beihang; i++)
    {
        if (i >= startLine && i < startLine + howmany_hang_i_will_process)
        {
            //MPI_Send(&m[i][0], lie, MPI_UNSIGNED, 0, 0, MPI_COMM_WORLD);

            for (int j = 0; j < numProcesses; j++)
            {
                if (j != rank)
                    MPI_Send(&m[i][0], lie, MPI_UNSIGNED, j, 0, MPI_COMM_WORLD);
            }
        }
        else
        {
            //if (rank == 0)
            MPI_Recv(&m[i][0], lie, MPI_UNSIGNED, i / howmany_hang_i_will_process, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        }
    }


    /* for (int i = 0; i < numProcesses; i++)
     {
         if (i == rank)
         {
             cout << rank << endl;
             testShow(m, beihang, lie, beilie);
             cout << endl;
         }
         MPI_Barrier(MPI_COMM_WORLD);
     }*/
    return m;
}




struct TransportData {
    int process_start_at_here;
    int temp;
};


int fuckTimes = 0;

streampos MPIUpdateZi(unsigned** zi, int howmany, int zilie, int lie, int beginHang, ifstream& fin, streampos headPos, int rank, int numProcesses)
{
    //ifstream fin;
    //fin.open(addr.c_str(), ios::in);
    int pos[32];
    for (int i = 0; i < howmany; i++)
        for (int p = 0; p < lie; p++)
            zi[i][p] = 0;
    for (int i = 0; i < 32; i++)
        pos[i] = 0;
    streampos nowHead = headPos;
    fin.seekg(headPos);
    char ch;
    int temp = 0, nowPos = 0, bitclimiter = 0, whetherBegin = 1, nowQujian = 0, lastQujian = 0, thisishang = 0, dotimes = 0;

    fuckTimes++;


    //MPI_Bcast(&missionQueue.data(), missionQueue.size(), MPI_INT, 0, MPI_COMM_WORLD);


     
    int** fenpei_recorderArr = new int*[howmany + 1];
    for (int i = 0; i < howmany; i++)
    {
        fenpei_recorderArr[i] = new int[2];
    }
    int fenpei_recorderSize = 0;
    //这里面，一个元素（a,b）表示在第a号进程处理了第b行消元子）

    streampos process_start_at_here = 0;
    int which_process_is_now = 1;

    while (dotimes < howmany )
    {
        if (!fin.get(ch))
        {
            if (rank == 0)
            {
                break;
            }
            else
            {
                MPI_Recv(&fenpei_recorderArr[fenpei_recorderSize][0], 2, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
                break;
            }
        }
        if (ch >= '0' && ch <= '9')
        {
            temp *= 10;
            temp += ch - '0';
        }
        else if (ch == ' ')
        {
            if (whetherBegin)
            {
                if (temp < beginHang - howmany)
                {
                    if (rank == 0)
                        break;
                    else
                    {
                        MPI_Recv(&fenpei_recorderArr[fenpei_recorderSize][0], 2, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
                        break;
                    }
                }
                else
                {

                    //接下来就要看分配给谁了
                    if (rank == 0)
                    {

                        lastQujian = qujian(temp, zilie);
                        bitclimiter = liePos(temp, zilie);
                        pos[bitclimiter] = 1;
                        whetherBegin = 0;
                        thisishang = beginHang - temp - 1;


                        //分配完任务后我就要一直ignore到换行
                        process_start_at_here = fin.tellg();
                        //TransportData toSendData;
                        //toSendData.process_start_at_here = process_start_at_here;
                        //toSendData.temp = temp;
                        ////int mission[2] = { process_start_at_here ,temp };
                        //fenpei_recorder.push_back(toSendData);

                        fenpei_recorderArr[fenpei_recorderSize][0] = process_start_at_here;
                        fenpei_recorderArr[fenpei_recorderSize][1] = temp;


                        MPI_Send(&fenpei_recorderArr[fenpei_recorderSize][0], 2, MPI_INT, which_process_is_now, 0, MPI_COMM_WORLD);

                        fenpei_recorderSize++;

                        which_process_is_now = (numProcesses - 1 == which_process_is_now) ? 1 : which_process_is_now + 1;
                        

                        //发送完成。现在我要开始ignore辣。
                        fin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
                        //已经到达了下一行
                        nowHead = fin.tellg();
                        for (int i = 0; i < 32; i++)
                            pos[i] = 0;
                        whetherBegin = 1;
                        dotimes++;
                        temp = 0;
                        nowQujian = 0;
                        lastQujian = 0;
                        continue;
                    }
                    else
                    {
                        //这里有可能出现没法整除，任务做完后有一两个进程还在苦等0号进程的情况。这个后面在处理。
                        //int mission[2];
                        // 
                        //TransportData reciveData;
                        //要是轮不到他就会一直卡住。


                        //cout << rank << " " << fenpei_recorderSize << endl;

                        MPI_Recv(&fenpei_recorderArr[fenpei_recorderSize][0], 2, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);


                        /*for (int i = 1; i <= fenpei_recorderSize; i++)
                        {
                            cout << rank << " " << i << " " << fenpei_recorderArr[i][0] << " " << fenpei_recorderArr[i][1] << endl;
                        }*/
                        if (fenpei_recorderArr[fenpei_recorderSize][1] == -1)//这个是发信号让他退出来。
                        {
                            break;
                        }

                        //fenpei_recorder.push_back(reciveData);
                        //取到temp
                        temp = fenpei_recorderArr[fenpei_recorderSize][1];
                        //文件读取位置移动到这里
                        fin.seekg(fenpei_recorderArr[fenpei_recorderSize][0]);

                        fenpei_recorderSize++;


                        lastQujian = qujian(temp, zilie);
                        bitclimiter = liePos(temp, zilie);
                        pos[bitclimiter] = 1;
                        whetherBegin = 0;
                        thisishang = beginHang - temp - 1;

                    }


                }
            }
            else
            {
                nowQujian = qujian(temp, zilie);//算出了temp所在的区间
                if (nowQujian != lastQujian)
                {
                    zi[thisishang][lastQujian] = bit2int(pos);
                    for (int i = 0; i < 32; i++)
                        pos[i] = 0;
                }
                bitclimiter = liePos(temp, zilie);//算出了temp所在的区间的位置。
                pos[bitclimiter] = 1;//该区间下对应位置记为1
                lastQujian = nowQujian;
            }
            temp = 0;
        }
        else if (ch == '\n')
        {
            nowHead = fin.tellg();
            zi[thisishang][lastQujian] = bit2int(pos);
            for (int i = 0; i < 32; i++)
                pos[i] = 0;
            whetherBegin = 1;
            dotimes++;
            temp = 0;
            nowQujian = 0;
            lastQujian = 0;
        }
    }
    //先让还没完成的退出来








    if (rank == 0)
    {
        MPI_Request request;
        //cout << fenpei_recorderSize << " " << howmany + 1 << endl;
        int temp[2] = { -1,-1 };
        //fenpei_recorderArr[fenpei_recorderSize][0] = -1;
        //fenpei_recorderArr[fenpei_recorderSize][1] = -1;
        for (int i = 1; i < numProcesses; i++)
        {
            MPI_Isend(&temp, 2, MPI_INT, i, 0, MPI_COMM_WORLD, &request);
        }
    }


    //写道里面去
    if (rank == 0)
    {
        for (int i = 0; i < fenpei_recorderSize; i += (numProcesses - 1))
        {

            for (int j = 1; j < numProcesses && i + j <= fenpei_recorderSize; j++)
            {
                MPI_Recv(&zi[beginHang - fenpei_recorderArr[i + j - 1][1] - 1][0], lie, MPI_UNSIGNED, j, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
            }
        }

    }
    else
    {

        for (int i = 0; i < fenpei_recorderSize; i++)
        {
            MPI_Send(&zi[beginHang - fenpei_recorderArr[i][1] - 1][0], lie, MPI_UNSIGNED, 0, 0, MPI_COMM_WORLD);
        }
    }



    delete[]fenpei_recorderArr;
    MPI_Bcast(&nowHead, 1, MPI_OFFSET, 0, MPI_COMM_WORLD);





    return nowHead;
}
streampos UpdateZi(unsigned** zi, int howmany, int zilie, int lie, int beginHang, ifstream& fin, streampos headPos)
{
    //ifstream fin;
    //fin.open(addr.c_str(), ios::in);
    int pos[32];
    for (int i = 0; i < howmany; i++)
        for (int p = 0; p < lie; p++)
            zi[i][p] = 0;
    for (int i = 0; i < 32; i++)
        pos[i] = 0;
    streampos nowHead = headPos;
    fin.seekg(headPos);
    char ch;
    int temp = 0, nowPos = 0, bitclimiter = 0, whetherBegin = 1, nowQujian = 0, lastQujian = 0, thisishang = 0, dotimes = 0;


    while (dotimes < howmany && fin.get(ch))
    {
        if (ch >= '0' && ch <= '9')
        {
            temp *= 10;
            temp += ch - '0';
        }
        else if (ch == ' ')
        {
            if (whetherBegin)
            {
                if (temp < beginHang - howmany)
                {
                    break;
                }
                else
                {
                    lastQujian = qujian(temp, zilie);
                    bitclimiter = liePos(temp, zilie);
                    pos[bitclimiter] = 1;
                    whetherBegin = 0;
                    thisishang = beginHang - temp - 1;
                }
            }
            else
            {
                nowQujian = qujian(temp, zilie);//算出了temp所在的区间
                if (nowQujian != lastQujian)
                {
                    zi[thisishang][lastQujian] = bit2int(pos);
                    for (int i = 0; i < 32; i++)
                        pos[i] = 0;
                }
                bitclimiter = liePos(temp, zilie);//算出了temp所在的区间的位置。
                pos[bitclimiter] = 1;//该区间下对应位置记为1
                lastQujian = nowQujian;
            }
            temp = 0;
        }
        else if (ch == '\n')
        {
            nowHead = fin.tellg();
            zi[thisishang][lastQujian] = bit2int(pos);
            for (int i = 0; i < 32; i++)
                pos[i] = 0;
            whetherBegin = 1;
            dotimes++;
            temp = 0;
            nowQujian = 0;
            lastQujian = 0;
        }
    }
    //fin.close();
    return nowHead;
}
int findinthead(unsigned int num, int lie, int qujian)
{
    int* pos = int2bit(num);
    for (int i = 0; i < 32; i++)
    {
        if (pos[i])
        {
            return lie - qujian * 32 - i - 1;
        }
    }
    return -1;
}
int findHead(unsigned int* m, int lie)//这里的列是01串的列
{
    for (int i = 0; i < lie; i++)
    {
        if (m[i])
        {
            return findinthead(m[i], lie, i);
        }
    }
    return -1;
}


bool isNotNull(unsigned int* m, int lie)
{
    for (int i = 0; i < lie; i++)
    {
        if (m[i])
        {
            return 1;
        }
    }
    return 0;
}
void AsubB(unsigned int* a, unsigned int* b, int lie)
{
    for (int i = 0; i < lie; i++)
    {
        a[i] = a[i] ^ b[i];
    }
}
void bingxingAsubB(unsigned int* a, unsigned int* b, int lie)
{
    /*int i = 0;
    __m256i t1, t2;
    for (i = 0; i + 8 < lie; i += 8)
    {
        t1 = _mm256_loadu_si256((__m256i*) & a[i]);
        t2 = _mm256_loadu_si256((__m256i*) & b[i]);
        t1 = _mm256_xor_si256(t1, t2);
        _mm256_storeu_si256((__m256i*) & a[i], t1);
    }
    for (; i < lie; i++)
    {
        a[i] = (a[i] == b[i]) ? 0 : 1;
    }*/


    int i = 0;
    for (i = 0; i + 4 < lie; i += 4)
    {
        __m128i t1 = _mm_loadu_si128((__m128i*) & a[i]);
        __m128i t2 = _mm_loadu_si128((__m128i*) & b[i]);
        t1 = _mm_xor_si128(t1, t2);
        _mm_storeu_si128((__m128i*) & a[i], t1);
    }

    for (; i < lie; i++)
    {
        a[i] = (a[i] == b[i]) ? 0 : 1;
    }
}


double common(unsigned** bei, int howmany, int beihang, int beilie, int zihang, int zilie, int whichTextIsNow, int bingOrCom)
{
    struct timeval t1, t2;
    double timeuse = 0;
    string ziAddr = getziAddr(whichTextIsNow);
    ifstream fin;
    fin.open(ziAddr.c_str(), ios::in);
    int lie = (beilie / 32 * 32 == beilie) ? beilie / 32 : beilie / 32 + 1;
    unsigned int** zi = init(howmany, lie);
    isNull = new bool[howmany];
    int beginHang = zihang;
    int times = (zihang / howmany * howmany == zihang) ? zihang / howmany : zihang / howmany + 1;
    streampos headPos = 0;
    bool* wetherThisHangIsOk = new bool[beihang];
    for (int i = 0; i < beihang; i++)
        wetherThisHangIsOk[i] = 0;
    int beishufuck = 1;
    for (int cycles = 0; cycles < times; cycles++)
    {
        /*if (times * beishufuck / 10 <= cycles)
        {
            cout << beishufuck << "0%" << endl;
            beishufuck++;
        }*/


        for (int i = 0; i < howmany; i++)
            isNull[i] = !isNotNull(zi[i], lie);
        gettimeofday(&t1, NULL);

        beginHang = zihang - cycles * howmany;
        headPos = UpdateZi(zi, howmany, zilie, lie, beginHang, fin, headPos);//这样子消元子就被更新了。



        for (int beiPos = 0; beiPos < beihang; beiPos++)
        {
            for (int ziPos = beginHang - 1; ziPos >= beginHang - howmany; ziPos--)
            {
                if (wetherThisHangIsOk[beiPos])
                    //whetherContinue = 1;
                    break;
                int nowHead = 0;
                int whetherBreak = 0;
                nowHead = findHead(bei[beiPos], zilie);
                if (nowHead >= beginHang - howmany && nowHead < beginHang)
                {
                    //zi[beginHang - nowHead - 1]是数组。我们要判断这玩意是不是空的
                    if (isNull[beginHang - nowHead - 1] == 0)
                        AsubB(bei[beiPos], zi[beginHang - nowHead - 1], lie);
                    else
                    {
                        wetherThisHangIsOk[beiPos] = 1;
                        for (int qqq = 0; qqq < lie; qqq++)
                            zi[beginHang - nowHead - 1][qqq] = bei[beiPos][qqq];
                        isNull[beginHang - nowHead - 1] = 0;
                    }

                }
                else ziPos = -114514;
            }
        }


        gettimeofday(&t2, NULL);
        timeuse += (t2.tv_sec - t1.tv_sec) + (double)(t2.tv_usec - t1.tv_usec) / 1000000.0;
    }
    //testShow(bei, beihang, lie, beilie);
    return timeuse;
}

double common2(int numProcesses, int rank,int argc, char* argv[], unsigned** bei, int howmany, int beihang, int beilie, int zihang, int zilie, int whichTextIsNow, int bingOrCom)
{

 


    struct timeval t1, t2;
    double timeuse = 0;
    string ziAddr = getziAddr(whichTextIsNow);
    ifstream fin;
    fin.open(ziAddr.c_str(), ios::in);
    int lie = (beilie / 32 * 32 == beilie) ? beilie / 32 : beilie / 32 + 1;
    unsigned int** zi = init(howmany, lie);
    isNull = new bool[howmany];
    int beginHang = zihang;
    int times = (zihang / howmany * howmany == zihang) ? zihang / howmany : zihang / howmany + 1;
    streampos headPos = 0;
    bool* wetherThisHangIsOk = new bool[beihang];
    for (int i = 0; i < beihang; i++)
        wetherThisHangIsOk[i] = 0;
    int beishufuck = 1;

    for (int cycles = 0; cycles < times; cycles++)
    {
        if (times * beishufuck / 10 <= cycles)
        {
            //cout << beishufuck << "0%" << endl;
            beishufuck++;
        }

        
        



        //这个地方我们并不需要多个进程一起，因为只有0号进程有正常的消元子。

        if (rank == 0)
            gettimeofday(&t1, NULL);

        beginHang = zihang - cycles * howmany;
        headPos = MPIUpdateZi(zi, howmany, zilie, lie, beginHang, fin, headPos, rank, numProcesses);//这样子消元子就被更新了。
        /*if (rank == 0)
        {
            cout << headPos << endl;
            testShow(zi, howmany, lie, zilie);
            cout << "fuck" << endl;
        }*/


            if (rank == 0)
            {
                for (int i = 0; i < howmany; i++)
                    isNull[i] = !isNotNull(zi[i], lie);
#pragma omp parallel num_threads(pThreadNum)
#pragma omp for //schedule(dynamic, 10)
                for (int beiPos = 0; beiPos < beihang; beiPos++)
                {
                    for (int ziPos = beginHang - 1; ziPos >= beginHang - howmany; ziPos--)
                    {
                        if (wetherThisHangIsOk[beiPos])
                            //whetherContinue = 1;
                            break;
                        int nowHead = 0;
                        int whetherBreak = 0;
                        nowHead = findHead(bei[beiPos], zilie);
#pragma omp critical
                        {
                            if (nowHead >= beginHang - howmany && nowHead < beginHang)
                            {
                                //zi[beginHang - nowHead - 1]是数组。我们要判断这玩意是不是空的
                                if (isNull[beginHang - nowHead - 1] == 0)
                                    bingxingAsubB(bei[beiPos], zi[beginHang - nowHead - 1], lie);
                                else
                                {
                                    wetherThisHangIsOk[beiPos] = 1;
                                    for (int qqq = 0; qqq < lie; qqq++)
                                        zi[beginHang - nowHead - 1][qqq] = bei[beiPos][qqq];
                                    isNull[beginHang - nowHead - 1] = 0;
                                }

                            }
                            else ziPos = -114514;
                        }
                    }
                }
            }




        if (rank == 0)
        {
            gettimeofday(&t2, NULL);
            timeuse += (t2.tv_sec - t1.tv_sec) + (double)(t2.tv_usec - t1.tv_usec) / 1000000.0;
        }
    }

    //if (rank == 0)testShow(bei, beihang, lie, beilie);
    fin.close();
    return timeuse;
}

int main(int argc, char* argv[])
{

    int provided;

    MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided);
    int numProcesses, rank;
    MPI_Comm_size(MPI_COMM_WORLD, &numProcesses);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    pThreadNum = 3;
    if (0)
    {//MPI_Init(&argc, &argv);
        for (int i = 11; i <= 11; i++)
        {
            struct timeval t1, t2;
            double timeuse = 0;
            if (rank == 0)
            {
                gettimeofday(&t1, NULL);
            }

            int beihang, beilie, zihang, zilie;
            int whichTextIsNow = i;
            beihang = getHang(whichTextIsNow);
            beilie = zihang = zilie = getLie(whichTextIsNow);
            string beiAddr = getbeiAddr(whichTextIsNow);
            unsigned int** bei = MPIwrite(beiAddr, beihang, beilie, rank, numProcesses);

            int howmany = 1000;

            double time = common2(numProcesses, rank, argc, argv, bei, howmany, beihang, beilie, zihang, zilie, whichTextIsNow, 0);
            //if (rank == 0)cout << time << endl;
            if (rank == 0)
            {
                gettimeofday(&t2, NULL);
                timeuse += (t2.tv_sec - t1.tv_sec) + (double)(t2.tv_usec - t1.tv_usec) / 1000000.0;
                cout << timeuse << endl;
            }
        }
    }
    else
    {

        for (int i = 11; i <= 11; i++)
        {
            struct timeval t1, t2;
            double timeuse = 0;
            gettimeofday(&t1, NULL);

            int beihang, beilie, zihang, zilie;
            int whichTextIsNow = i;
            beihang = getHang(whichTextIsNow);
            beilie = zihang = zilie = getLie(whichTextIsNow);
            string beiAddr = getbeiAddr(whichTextIsNow);
            unsigned int** bei = write(beiAddr, beihang, beilie,0,0);
            //unsigned int** bei = MPIwrite(beiAddr, beihang, beilie, rank, numProcesses);


            int howmany = 1000;

            double time = common(bei, howmany, beihang, beilie, zihang, zilie, whichTextIsNow, 0);
            //if (rank == 0)cout << time << endl;
            gettimeofday(&t2, NULL);
            timeuse += (t2.tv_sec - t1.tv_sec) + (double)(t2.tv_usec - t1.tv_usec) / 1000000.0;
            cout << timeuse << endl;
        }
    }
    return 0;
}

